#pragma once

#include <iostream>
#include <string>
#include <set>
#include <fstream>

#include "Log.hpp"

const std::string sep = " ";

class Command
{
private:
	void Loadconf(const std::string &condf)
	{
		// 先打开文件流
		std::fstream in(condf);
		if (!in.is_open())
		{
			LOG(FATAL, "open %s error\n", condf.c_str());
			return;
		}
		// 每次循环获取一行数据
		std::string line;
		while (std::getline(in, line))
		{
			LOG(DEBUG, "load command [%s] success\n", line.c_str());

			// 存放到哈希表中，也就是加载到内存
			_safe_cmd.insert(line);
		}

		in.close();
	}

public:
	Command(const std::string &cond_path)
		: _cond_path(cond_path)
	{
		Loadconf(_cond_path);
	}

	std::string PrefixCommand(const std::string &cmd)
	{
		if (cmd.empty())
			return std::string();
		auto pos = cmd.find(sep);
		if (pos == std::string::npos)
			return cmd;
		else
			return cmd.substr(0, pos);
	}

	bool SafeCheck(const std::string &cmd)
	{
		std::string prefix = PrefixCommand(cmd);
		auto iter = _safe_cmd.find(prefix);
		if (iter == _safe_cmd.end())
			return false;
		return true;
	}

	std::string Excute(const std::string &cmd)
	{
		// 检测安全，不能让有交互命令控制
		std::string result;
		if (SafeCheck(cmd))
		{
			FILE *fp = popen(cmd.c_str(), "r");
			if (fp == nullptr)
			{
				return "failed";
			}
			char buffer[1024];
			while(fgets(buffer,sizeof(buffer),fp) != NULL)
			{
				result += buffer;
			}

			pclose(fp);
		}
		else
		{
			result = "bad people\n";
		}

		return result;
	}

	~Command()
	{
	}

private:
	std::set<std::string> _safe_cmd;
	std::string _cond_path;
};